package service

import (
	"encoding/json"
	"errors"
	"haiqiu-go-admin/dao"
	"haiqiu-go-admin/entity"
	"haiqiu-go-admin/entity/dto"
	"haiqiu-go-admin/entity/vo"
	"haiqiu-go-admin/result"
	"haiqiu-go-admin/utils"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"
)

func MenuRouter(username string) (*[]vo.RouterVo, error) {
	var permissions []entity.SysPermission
	if username == "admin" {
		menus, err := dao.MenuList(new(dto.MenuQueryParams))
		if err != nil {
			return nil, err
		}
		permissions = menus
	} else {
		menus, err := dao.MenuListByUserName(username)
		if err != nil {
			return nil, err
		}
		permissions = *menus
	}

	routerVos := make([]vo.RouterVo, 0)
	for _, permission := range permissions {
		var router vo.RouterVo
		router.Id = permission.Id
		router.ParentId = permission.ParentId
		if permission.Component == "#" {
			router.Component = "Layout"
		} else {
			router.Component = permission.Component
		}
		metaVo := vo.MetaVo{
			Title:   permission.Title,
			Icon:    permission.Icon,
			NoCache: false,
			Link:    nil,
		}
		router.Meta = &metaVo
		router.Path = permission.Path
		router.Hidden = false
		router.Name = permission.Title
		if strings.HasPrefix(permission.Path, "http") && permission.IsFrame {
			router.Meta.Link = &permission.Path
		}
		if permission.Type != "2" {
			routerVos = append(routerVos, router)
		}
	}
	return selectRouterList(routerVos), nil
}

func selectRouterList(routerVos []vo.RouterVo) *[]vo.RouterVo {
	finalRouterVos := make([]vo.RouterVo, 0)
	for _, router := range routerVos {
		if router.ParentId == 0 {
			finalRouterVos = append(finalRouterVos, createChildRouter(router, routerVos))
		}
	}
	return &finalRouterVos
}

func createChildRouter(routerVo vo.RouterVo, routerVos []vo.RouterVo) vo.RouterVo {
	routerVo.Children = make([]vo.RouterVo, 0)
	for _, child := range routerVos {
		if child.ParentId == routerVo.Id {
			if len(child.Children) != 0 {
				child.Redirect = "noRedirect"
			} else {
				child.AlwaysShow = false
				child.Redirect = child.Path
			}
			routerVo.Children = append(routerVo.Children, createChildRouter(child, routerVos))
		}
	}
	return routerVo
}

// MenuById 根据ID查询数据
func MenuById(w http.ResponseWriter, r *http.Request) (any, error) {
	formatJson := utils.GetParamsFormatJson(w, r)
	menuIdStr := formatJson["id"][0]
	menuId, err := strconv.ParseInt(menuIdStr, 10, 64)
	if err != nil {
		panic(err)
		return nil, err
	}
	menu, err := dao.MenuById(menuId)
	if err != nil {
		return nil, err
	}
	return &menu, nil
}

// MenuPage 分页查询
func MenuPage(w http.ResponseWriter, r *http.Request) (any, error) {
	formatJson, err := utils.GetBodyFormatJson(w, r)
	if err != nil {
		return nil, errors.New(result.ParamsErr)
	}
	var page = dto.PageDto{}
	err = json.Unmarshal(formatJson, &page)
	if err != nil {
		log.Println(err)
	}
	count := dao.MenuPageCount()
	if count == 0 {
		return nil, nil
	}
	var pageData vo.PageData
	list, err := dao.MenuPageList((page.PageIndex-1)*page.PageSize, page.PageSize)
	pageData.Data = list
	pageData.Total = count
	pageData.PageIndex = page.PageIndex
	pageData.PageSize = page.PageSize
	if err != nil {
		return nil, err
	}
	return pageData, nil
}

// MenuAdd 新增数据
func MenuAdd(w http.ResponseWriter, r *http.Request) (any, error) {
	formatJson, err := utils.GetBodyFormatJson(w, r)
	if err != nil {
		return nil, err
	}
	var sysMenu = entity.SysPermission{}
	err = json.Unmarshal(formatJson, &sysMenu)
	if err != nil {
		return nil, err
	}
	var nowTime = time.Now()
	sysMenu.CreateTime = &nowTime
	sysMenu.UpdateTime = &nowTime
	add, err := dao.MenuAdd(&sysMenu)
	if err != nil {
		return nil, err
	}
	return add, nil
}

// MenUpdate 根据ID更新数据
func MenUpdate(w http.ResponseWriter, r *http.Request) (any, error) {
	formatJson, err := utils.GetBodyFormatJson(w, r)
	if err != nil {
		return nil, err
	}
	var sysMenu = entity.SysPermission{}
	err = json.Unmarshal(formatJson, &sysMenu)
	if err != nil {
		return nil, err
	}
	var nowTime = time.Now()
	sysMenu.UpdateTime = &nowTime
	add, err := dao.MenuUpdate(&sysMenu)
	if err != nil {
		return nil, err
	}
	return add, nil
}

// MenuDeleteBatch 批量删除数据
func MenuDeleteBatch(w http.ResponseWriter, r *http.Request) (any, error) {
	formatJson, err := utils.GetBodyFormatJson(w, r)
	if err != nil {
		return nil, err
	}
	var ids []int64
	err = json.Unmarshal(formatJson, &ids)
	if err != nil {
		return nil, err
	}

	add, err := dao.MenuDeleteBatch(ids)
	if err != nil {
		return nil, err
	}
	return add, nil
}

// MenuList 查询所有数据
func MenuList(w http.ResponseWriter, r *http.Request) (*[]entity.SysPermission, error) {
	formatJson, err := utils.GetBodyFormatJson(w, r)
	if err != nil {
		log.Println(err.Error())
		return nil, err
	}
	var menuQueryDto dto.MenuQueryParams
	if len(formatJson) == 0 {
		menuList, err := dao.MenuList(new(dto.MenuQueryParams))
		if err != nil {
			log.Println(err.Error())
			return nil, err
		}
		return &menuList, nil
	}
	err = json.Unmarshal(formatJson, &menuQueryDto)
	if err != nil {
		log.Println(err.Error())
		return nil, err
	}
	menuList, err := dao.MenuList(&menuQueryDto)
	if err != nil {
		log.Println(err.Error())
		return nil, err
	}
	return &menuList, nil
}

// 角色ID查询菜单ID集合与菜单下拉树结构 查询所有数据
func RoleMenuTreeSelect(w http.ResponseWriter, r *http.Request) (any, error) {
	formatJson := utils.GetParamsFormatJson(w, r)
	idStr := formatJson["roleId"][0]
	roleId, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		log.Println(err.Error())
		return nil, err
	}
	menus, err := dao.MenuByRoleId(roleId)
	if err != nil {
		log.Println(err.Error())
		return nil, err
	}
	var menuIds []int64
	for i := 0; i < len(*menus); i++ {
		menuIds = append(menuIds, (*menus)[i].Id)
	}
	treeData, err := TreeMenu(w, r)
	if err != nil {
		log.Println(err.Error())
		return nil, err
	}
	mpaData := make(map[string]any)
	mpaData["menus"] = treeData
	mpaData["checkedKeys"] = menuIds
	return &mpaData, nil
}

func TreeMenu(w http.ResponseWriter, r *http.Request) (treeData any, err error) {
	menus, err := dao.MenuList(new(dto.MenuQueryParams))
	if err != nil {
		return nil, err
	}
	vos := make([]vo.MenuVo, 0)
	for _, v := range menus {
		var data vo.MenuVo
		data.Id = v.Id
		data.ParentId = v.ParentId
		data.Title = v.Title
		data.Value = v.Value
		data.Icon = v.Icon
		data.Path = v.Path
		data.Active = v.Active
		data.Desc = v.Desc
		data.Method = v.Method
		data.Sort = v.Sort
		data.Component = v.Component
		data.Type = v.Type
		data.IsFrame = v.IsFrame
		data.IsCache = v.IsCache
		data.CreateTime = v.CreateTime
		data.UpdateTime = v.UpdateTime
		vos = append(vos, data)
	}
	if err != nil {
		log.Println(err.Error())
		return nil, err
	}
	return menuTreeDataList(vos), nil
}

func menuTreeDataList(vos []vo.MenuVo) *[]vo.MenuVo {
	finalMenuVos := make([]vo.MenuVo, 0)
	for _, dept := range vos {
		if dept.ParentId == 0 {
			finalMenuVos = append(finalMenuVos, menuChildrenList(dept, vos))
		}
	}
	return &finalMenuVos
}

func menuChildrenList(menu vo.MenuVo, vos []vo.MenuVo) vo.MenuVo {
	menu.Children = make([]vo.MenuVo, 0)
	for _, child := range vos {
		if child.ParentId == menu.Id {
			menu.Children = append(menu.Children, menuChildrenList(child, vos))
		}
	}
	return menu
}
